/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.ericsson.nfc.signing.algorithm;

import com.ericsson.nfc.signing.record.CertificateBytes;
import com.ericsson.nfc.signing.record.SignatureField;
import com.ericsson.nfc.signing.record.SignatureRecord;
import com.ericsson.nfc.signing.record.URIRecord;
import java.math.BigInteger;
import org.bouncycastle.asn1.DEREncodable;
import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.DSAParameter;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;

//#ifdef MyJSR257
//# import my.javax.microedition.contactless.ndef.NDEFRecordType;
//#else
import javax.microedition.contactless.ndef.NDEFRecordType;
//#endif

/**
 *
 * @author emarkki
 */
public class DSASigner extends Signer {

    private static final DERObjectIdentifier ALG_ID = DSAVerifier.id_dsa;
    
    public DSASigner(PrivateKey privateKey, int certificateType, CertificateBytes[] chain, URIRecord certURI, NDEFRecordType signatureRecordType) {
        super(SignatureField.DSA, privateKey, certificateType, chain, certURI, signatureRecordType);
                
        if(!ALG_ID.equals(privateKey.getPrivateKeyInfo().getAlgorithmId().getObjectId())) {
            throw new WrongPrivateKeyAlgorithm("Private key algorithm is not DSA");
        }
    }

    public DSASigner(PrivateKey privateKey, int certificateType, CertificateBytes[] chain, URIRecord certURI) {
        this(privateKey, certificateType, chain, certURI, SignatureRecord.RECORD_TYPE);
    }
    
    public byte[] sign(byte[] coveredBytes) throws SignatureException, DataLengthException {
        try {
            BigInteger[] rs = signUsingDSA(coveredBytes, getPrivateKey());
            return DSAVerifier.encode(rs[0], rs[1]);
        } catch (CryptoException ex) {
            ex.printStackTrace();
            throw new SignatureException(ex);
        }
    }

    static BigInteger[] signUsingDSA(byte[] coveredBytes, PrivateKey privKey) throws DataLengthException, CryptoException {
        
        PrivateKeyInfo pkKeyInfo = privKey.getPrivateKeyInfo();
        
        DERInteger derX = (DERInteger)pkKeyInfo.getPrivateKey();
        DEREncodable de = pkKeyInfo.getAlgorithmId().getParameters();

        DSAParameters parameters = null;
        if (de != null) {
            DSAParameter params = DSAParameter.getInstance(de.getDERObject());
            parameters = new DSAParameters(params.getP(), params.getQ(), params.getG());
        }

        DSAPrivateKeyParameters privParameters = new DSAPrivateKeyParameters(derX.getValue(), parameters);
                                
        Digest digest = DigestFactory.getDigest("SHA-1");
        digest.update(coveredBytes, 0, coveredBytes.length);
        byte[] digestBytes = new byte[digest.getDigestSize()];
        digest.doFinal(digestBytes, 0);

        // Bouncy castle signer
        org.bouncycastle.crypto.signers.DSASigner signer = new org.bouncycastle.crypto.signers.DSASigner();
        signer.init(true, privParameters);
        
        // Signature
        return signer.generateSignature(digestBytes);
    }

}
